<script setup lang="ts">
    import {onMounted, reactive, ref, nextTick} from 'vue'
    import { userInfoAPI, addOrUpdateUserAPI, allRoleAPI, setUserRoleAPI, removeUserAPI, selectRemoveUserAPI } from '@/network/acl/user';
    import type { UserResponseData, Records, User, AllRoleResponseData, AllRole, SetRoleData} from '@/network/acl/user/type';
    import { ElMessage } from 'element-plus';
    // 当前页面
    const pageNO = ref<number>(1)
    // 每一页展示数据条数
    const limit = ref<number>(5)
    const total = ref<number>(0)
    const userArr = ref<Records>([])
   async function getUserInfo(page = 1) {
        pageNO.value = page
        const res: UserResponseData = await userInfoAPI(pageNO.value, limit.value, keyword.value)
        // console.log(res);
        if (res.code === 200) {
            userArr.value = res.data.records
            total.value = res.data.total
        }
    }
    onMounted(() => {
        getUserInfo()
    })

    // 每页条数变化
    function sizeChange() {
        getUserInfo()
    }

    // 控制抽屉
    const drawer = ref<boolean>(false)
    
    // 收集用户信息
    let userParams = reactive<User>({
        username: '',
        password: '',
        name: ''
    })
    // 添加用户
    function addUser() {
        // 先清空数据，再添加
        // 如果先修改，会遗留id 再次添加时，需要删除，避免影响后续判断
        delete userParams.id
        Object.assign(userParams, {
            username: '',
            password: '',
            name: ''
        }) 
        drawer.value = true
        // 清除校验信息
        nextTick(() => {
            form.value.clearValidate()
        })
    }

    // 修改
    function updateUser(row: User) {
        drawer.value = true
        // 需用深拷贝，浅拷贝，两个对象之间会互相影响
        Object.assign(userParams, JSON.parse(JSON.stringify(row)))
        // 清除校验信息
        nextTick(() => {
            form.value.clearValidate()
        })
    }

    // 保存
    const form = ref()
   async function save() {
    // 表单校验全部通过再请求
    await form.value.validate()
        const res = await addOrUpdateUserAPI(userParams)
        console.log(res);
        if (res.code === 200) {
            ElMessage({
                type: 'success',
                message: userParams.id ? '修改成功' : '添加成功'
            })
            getUserInfo(userParams.id ? pageNO.value : 1)
            // 防止改了已登录的账号，页面会出现已登录名称和修改不一致；
            // 所以在修改之后，刷新浏览器一次，路由前置守卫，就会去重新获取用户信息，
            // 由于修改了登录名称，导致token失效，退回登录页
            window.location.reload()
        } else {
            ElMessage({
                type: 'error',
                message: userParams.id ? '修改失败' : '添加失败'
            })
        }
        drawer.value = false
    }

    // 取消
    function cancel() {
        drawer.value = false
    }

    // 表单校验
    // 规则
    // 校验用户名
    function validatorUsername(rule: any, value: any, callback: any) {
        // console.log(value);
        if (value.trim().length >= 5) {
            callback()
        } else {
            callback(new Error('用户名大于等于5位'))
        }
    }
    function validatorName(rule: any, value: any, callback: any) {
        if (value.trim().length >= 5) {
            callback()
        } else {
            callback(new Error('昵称大于等于5位'))
        }
    }
    function validatorPassword(rule: any, value: any, callback: any) {
        if (value.trim().length >= 5) {
            callback()
        } else {
            callback(new Error('密码大于等于6位'))
        }
    }
    
    const rules = {
        username: [
            {required: true, trigger: 'blur', validator: validatorUsername}
        ],
        name: [
            {required: true, trigger: 'blur', validator: validatorName}
        ],
        password: [
            {required: true, trigger: 'blur', validator: validatorPassword}
        ],
    }

    // 抽屉：分配角色
    const drawer2 = ref<boolean>(false)

   async function setRole(row: User) {
        // 如果当前点击了全选，点击其他职位时，需清空全选
        checkAll.value = false
        Object.assign(userParams, row)
        // 发请求获取全部职位和已有职位
        const res: AllRoleResponseData = await allRoleAPI(row.id)
        console.log(res);
        if (res.code === 200) {
            allRole = res.data.allRolesList
            userRole.value = res.data.assignRoles
            // 初始化时，如果已选中角色为零，那么不确定样式移除
            if (userRole.value.length === 0) {
                isIndeterminate.value = false
            }
            // 由于点击其他职位时，需清空全选，导致不确定样式消失，需再次判断
            if (userRole.value.length !== 0) {
                isIndeterminate.value = true
            }
            // 显示抽屉
            drawer2.value = true
        }
    }
    // 全选框收集数据
    const checkAll = ref<boolean>(false)
    // 全选框不确定状态样式
    const isIndeterminate = ref<boolean>(true)
    // 所有职位
    let allRole = <AllRole>[]
    // 已选中职位
    const userRole = ref<AllRole>([])
    
    // 全选框变化触发
    function handleCheckAllChange(val: boolean) {
        // val是true或者false
        // console.log(val);
        userRole.value = val ? allRole : []
        isIndeterminate.value = false
    }
    
    // 底部复选框发生变化触发
    function handleCheckedChange(value: string[]) {
        // value 是已选中职位的数组
        // console.log(value);
        const  checkedCount = value.length
        checkAll.value = checkedCount === allRole.length
        isIndeterminate.value = checkedCount < allRole.length && checkedCount > 0
        // 第二种判断（不确定状态样式）
        // isIndeterminate.value = !(allRole.length === checkedCount) && checkedCount > 0
    }


    // 添加职位确定按钮
   async function handleSetRole() {
        const data: SetRoleData = {
            userId: userParams.id,
            roleIdList: userRole.value.map(item => {
                return item.id
            })
        }
        const res: any = await setUserRoleAPI(data)
        console.log(res);
        if (res.code === 200) {
            ElMessage({
                type: 'success',
                message: '分配职位成功'
            })
            getUserInfo(pageNO.value)
            drawer2.value = false
            // 页面刷新，展现出该有的权限
            window.location.reload()
        } else {
            ElMessage({
                type: 'error',
                message: '分配职务失败'
            })
        }
    }

    // 添加职位取消按钮
    function setRolecancel() {
        drawer2.value = false
    }

    // 单个删除用户
   async function deleteUser(row: User) {
        const res: any = await removeUserAPI(row.id)
        console.log(res);
        if (res.code === 200) {
            ElMessage({
                type: 'success',
                message: '删除用户成功'
            })
            getUserInfo(userArr.value.length > 1 ? pageNO.value : pageNO.value - 1)
        } else {
            ElMessage({
                type: 'error',
                message: '删除用户失败'
            })
       }
    }

    // 用于收集批量删除参数的id数组
    let idList = ref<number[]>([])

    // 表格复选框选择变化
    function selectChange(value: Records) {
        idList.value = value.map(item => {
            return item.id
        })
        // console.log(idList.value);
    }

    // 批量删除方法
   async function selectDeleteUser() { 
    // 批量删除参数的id数组长度为0，就阻止发请求
        if (idList.value.length === 0) return
       const res: any = await selectRemoveUserAPI(idList.value)
       console.log(res);
       if (res.code === 200) {
            ElMessage({ 
                type: 'success',
                message: '删除用户成功'
            })
            getUserInfo(userArr.value.length === idList.value.length ? pageNO.value - 1 : pageNO.value)
       } else {
            ElMessage({
                type: 'error',
                message: '删除用户失败'
            })
       }
    }

    // 
    // 搜索：收集用户输入关键字
    const keyword = ref<string>('')
    function search() {
        // 根据关键字，获取对应的数据
        getUserInfo()
        // 清空关键字
        keyword.value = ''
    }

    import { storeToRefs } from 'pinia';
    import { useLayoutSettingStore } from '@/store/modules/setting';
    // 改变仓库里的refresh属性，main展示区会监测refresh变化，然后销毁重建main
    const {refresh} = storeToRefs(useLayoutSettingStore())
    // 重置
    function reset() {
        refresh.value = !refresh.value
    }
</script> 


<template>
   <div>
        <el-card>
            <el-form :inline="true" class="form">
                <el-form-item label="用户名：">
                    <el-input v-model="keyword" placeholder="请输入搜索用户名"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-button @click="search" :disabled="!keyword" type="primary">搜索</el-button>
                    <el-button type="primary" @click="reset">重置</el-button>
                </el-form-item>
            </el-form>    
        </el-card>
        <el-card style="margin: 10px 0;">
                <el-button v-has="'btn.User.add'" type="primary" @click="addUser">添加用户</el-button>
                <el-button type="primary" :disabled="idList.length === 0" @click="selectDeleteUser">批量删除</el-button>
                <el-table @selection-change="selectChange" style="margin: 10px 0;" border :data="userArr">
                    <el-table-column type="selection" align="center" ></el-table-column>
                    <el-table-column type="index" label="#" align="center"></el-table-column>
                    <el-table-column prop="id" label="ID" align="center"></el-table-column>
                    <el-table-column prop="username" label="用户名字" show-overflow-tooltip align="center"></el-table-column>
                    <el-table-column prop="name" label="用户名称" show-overflow-tooltip align="center"></el-table-column>
                    <el-table-column prop="roleName" label="用户角色" show-overflow-tooltip align="center"></el-table-column>
                    <el-table-column prop="createTime" label="创建时间" show-overflow-tooltip align="center"></el-table-column>
                    <el-table-column prop="updateTime" label="更新时间" show-overflow-tooltip align="center"></el-table-column>
                    <el-table-column label="操作" width="300px" align="center">
                        <template #="{row, $index}">
                            <el-button v-has="'btn.User.assgin'" @click="setRole(row)" type="primary" size="small" icon="User">分配角色</el-button>
                            <el-button v-has="'btn.User.update'" @click="updateUser(row)" type="primary" size="small" icon="Edit">编辑</el-button>
                            <el-popconfirm @confirm="deleteUser(row)" :title="`确定要删除${row.name}吗？`" width="230px">
                                <template #reference>
                                    <el-button v-has="'btn.User.remove'" type="danger" size="small" icon="Delete">删除</el-button>
                                </template>
                            </el-popconfirm>
                        </template>
                    </el-table-column>
                </el-table>
                <el-pagination
                v-model:current-page="pageNO"
                v-model:page-size="limit"
                :page-sizes="[5, 7, 9, 11]"
                :background="true"
                layout="prev, pager, next, jumper, -> ,total, sizes,"
                :total="total"
                @current-change="getUserInfo"
                @size-change="sizeChange"
                />
        </el-card>
        <!-- 抽屉：添加与修改 -->
        <el-drawer v-model="drawer">
            <template #header>
                <h4>{{ userParams.id ? '修改用户' : '添加用户' }}</h4>
            </template>
            <template #default>
                <el-form ref="form" :model="userParams" :rules="rules">
                    <el-form-item prop="username" label="用户名字">
                        <el-input v-model="userParams.username" placeholder="请填写用户姓名"></el-input>
                    </el-form-item>
                    <el-form-item prop="name" label="用户名称">
                        <el-input v-model="userParams.name" placeholder="请填写用户昵称"></el-input>
                    </el-form-item>
                    <el-form-item v-if="!userParams.id" prop="password" label="用户密码">
                        <el-input v-model="userParams.password" placeholder="请填写用户密码"></el-input>
                    </el-form-item>
                </el-form>
            </template>
            <template #footer>
                <div style="flex: auto">
                    <el-button @click="cancel">取消</el-button>
                    <el-button type="primary" @click="save">确定</el-button>
                </div>
            </template>
        </el-drawer>
        <!-- 抽屉：分配角色 -->
        <el-drawer v-model="drawer2">
            <template #header>
            <h4>分配角色</h4>
            </template>
            <template #default>
                <el-form>
                    <el-form-item label="用户姓名">
                        <el-input :disabled="true" v-model="userParams.name"></el-input>
                    </el-form-item>
                    <el-form-item label="职位列表">
                        <el-checkbox
                            v-model="checkAll"
                            :indeterminate="isIndeterminate"
                            @change="handleCheckAllChange" style="margin-right: 10px;">
                            全选
                        </el-checkbox>
                        <el-checkbox-group
                            v-model="userRole"
                            @change="handleCheckedChange"> 
                            <el-checkbox v-for="role in allRole" :key="role.id" :label="role" :value="role">
                                {{ role.roleName }}
                            </el-checkbox>
                        </el-checkbox-group>
                    </el-form-item>
                </el-form>
            </template>
            <template #footer>
            <div style="flex: auto">
                <el-button @click="setRolecancel">取消</el-button>
                <el-button type="primary" @click="handleSetRole">确定</el-button>
            </div>
            </template>
        </el-drawer>
   </div>
</template>


<style scoped lang='scss'>
    .form{
        display: flex;
        justify-content: space-between;
        align-items: center;
       
    }
</style>